package parsers;

import gui.MainFrame;
import java.awt.Frame;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import notifiers.MailSender;
import notifiers.SmsSender;
import rsshunter.DB;
import rsshunter.RSSBase;
import rsshunter.RSSChannel;
import rsshunter.RSSKeyword;

/**
 * Abstract class for parser implementations. It handles comunication with
 * MainFrame and parsers synchronization.
 */
public abstract class AbstractParser implements Parser {

    protected final MailSender mailSender;
    protected final SmsSender smsSender;
    protected final DB db = new DB();
    protected int progressStep = 0;
    protected final MainFrame parentFrame;
    private JProgressBar progressBar;

    protected abstract void parse(RSSBase base);

    public AbstractParser(MainFrame parent, MailSender mailSender,
            SmsSender smsSender) {
        this.smsSender = smsSender;
        this.mailSender = mailSender;
        this.parentFrame = parent;
        this.progressBar = parent.getProgressBar();
    }

    @Override
    public void checkBase(RSSBase base) {
        new Thread(new ParserWorker(base)).start();
    }

    /**
     * Get channels for given base from databse.
     *
     * @param base RSSBase name.
     * @return List of channels.
     */
    protected List<RSSChannel> getChannels(RSSBase base) {
        return db.getChannels(base.getName());
    }

    /**
     * Get keywords for given base from databse.
     *
     * @param base RSSBase name.
     * @return List of keywords.
     */
    protected List<RSSKeyword> getKeywords(RSSBase base) {
        return db.getKeywords(base.getName());
    }

    /**
     * Initializes progress bar in main frame.
     */
    protected void initProgressBar() {
        // Reset progressBar
        if (progressBar != null) {
            progressBar.setValue(0);
        }
    }

    /**
     * Increments progress by step on progress bar.
     */
    protected void incrementProgress() {
        if (progressBar != null) {
            progressBar.setValue(progressBar.getValue() + progressStep);
        }
    }

    /**
     * Shows on parent frame that feeding is finished.
     */
    protected void finalizeParentFrame(String baseName) {
        if (progressBar != null) {
            // Fill up progress bar
            progressBar.setValue(progressBar.getMaximum());
        }
        parentFrame.enableCheckButton(true);
        parentFrame.refresh();
        parentFrame.setStatus("Feeding base "
                + baseName + " finished.");
    }

    /**
     * Displays authentication error at parent frame. Gets focus.
     *
     * @param message Error message.
     * @param title Error title.
     */
    protected void displayAuthenticationError(String message, String title) {
        parentFrame.setState(Frame.NORMAL);
        parentFrame.toFront();
        JOptionPane.showMessageDialog(parentFrame,
                message,
                title,
                JOptionPane.ERROR_MESSAGE);
    }

    /**
     * ParserWorker is checking for new content in given RSSBase.
     */
    private class ParserWorker implements Runnable {

        private RSSBase base;

        public ParserWorker(RSSBase base) {
            this.base = base;
        }

        @Override
        public void run() {
            synchronized (AbstractParser.class) {
                parentFrame.enableCheckButton(false);
                initProgressBar();
                parse(base);
                finalizeParentFrame(base.getName());
            }
        }
    }
}
